﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using Locator.Silverlight.Client.Models.ViewModels.Elements;
using Locator.Silverlight.Client.Models.ProductsServiceReference;
using GalaSoft.MvvmLight.Command;

namespace Locator.Silverlight.Client.Models.ViewModels.Screens
{
    public class ManageProductsViewModel : ViewModelBase
    {
        private readonly IProductModel productModel;

        /// <summary>
        /// Initializes a new instance of the ManageProductsViewModel class.
        /// </summary>
        public ManageProductsViewModel()
            : this(new ProductModel())
        {

        }

        /// <summary>
        /// Initializes a new instance of the ManageProductsViewModel class.
        /// </summary>
        /// <param name="productModel"></param>
        public ManageProductsViewModel(IProductModel productModel)
        {
            this.productModel = productModel;
            if (IsInDesignMode)
            {
#if DEBUG
                //this.UserProducts = new ObservableCollection<ProductViewModel>() { 
                //    new ProductViewModel(new Product() { ID = 123, Name = "Domaine De La Seigneurie Des Tourelles Saumur 2008 750 mL bottle" }),
                //    new ProductViewModel(new Product() { ID = 124, Name = "Product 124" })
                //};

                //for (int i = 0; i < 20; i++)
                //{
                //    this.UserProducts.Add(new ProductViewModel(new Product() { ID = i, Name = "Product " + i }));
                //}

                this.SearchResults = new ObservableCollection<UserProductViewModel>() { 
                    new UserProductViewModel(new UserProduct() { UsedByUser = false, Id = 123, Name = "Domaine De La Seigneurie Des Tourelles Saumur 2008 750 mL bottle" }),
                    new UserProductViewModel(new UserProduct() { UsedByUser = false, Id = 124, Name = "Product 124" })
                };

                for (int i = 0; i < 20; i++)
                {
                    this.SearchResults.Add(new UserProductViewModel(new UserProduct() { UsedByUser = i % 2 == 0, Id = i, Name = "Product " + i }));
                }
#endif
            }
            else
            {
                this.SearchResults = new ObservableCollection<UserProductViewModel>();
                this.Refresh();
            }

            this.FindProductsCommand = new RelayCommand(() => this.FindProducts());
            this.AddProductCommand = new RelayCommand<UserProductViewModel>((product) => this.AddProduct(product));
            this.RemoveProductCommand = new RelayCommand<ProductViewModel>((product) => this.RemoveProduct(product));
        }

        private void Refresh()
        {
            this.productModel.GetAllSubstancesAsync((substances, error) =>
            {
                if (error != null)
                {
                    // Display error, normally this would be done through a property
                    MessageBox.Show(error.Message);
                    return;
                }

                this.AllSubstances = new ObservableCollection<SubstanceViewModel>(substances);
            });

            this.productModel.GetProductsForUserAsync((products, error) =>
            {
                if (error != null)
                {
                    // Display error, normally this would be done through a property
                    MessageBox.Show(error.Message);
                    return;
                }

                //this.UserProducts = new ObservableCollection<ProductViewModel>(products);
            });
        }

        private void AddProduct(UserProductViewModel product)
        {
            this.productModel.AddProductForUserAsync(product, (error) =>
            {
                if (error != null)
                {
                    // Display error, normally this would be done through a property
                    MessageBox.Show(error.Message);
                    return;
                }

                product.UsedByUser = true;
                this.UserProducts.Add(new ProductViewModel() { Id = product.Id, Name = product.Name });
                //MessageBox.Show("Success");
            });
        }

        private void RemoveProduct(ProductViewModel product)
        {
            this.productModel.DeleteProductForUserAsync(product, (error) =>
            {
                if (error != null)
                {
                    // Display error, normally this would be done through a property
                    MessageBox.Show(error.Message);
                    return;
                }


                this.UserProducts.Remove(product);
                foreach (UserProductViewModel userProduct in this.SearchResults)
                {
                    if (userProduct.Id == product.Id)
                    {
                        userProduct.UsedByUser = false;
                    }
                }
                //MessageBox.Show("Success");
            });
        }

        public RelayCommand<UserProductViewModel> AddProductCommand { get; private set; }

        public RelayCommand<ProductViewModel> RemoveProductCommand { get; private set; }

        /// <summary>
        /// The <see cref="UserProducts" /> property's name.
        /// </summary>
        public const string UserProductsPropertyName = "UserProducts";

        private ObservableCollection<ProductViewModel> userProducts;

        /// <summary>
        /// Gets the UserProducts property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<ProductViewModel> UserProducts
        {
            get { return ViewModelLocator.MainStatic.Products; }
            //userProducts; }

            //set
            //{
            //    if (userProducts == value)
            //    {
            //        return;
            //    }

            //    userProducts = value;

            //    // Update bindings, no broadcast
            //    RaisePropertyChanged(UserProductsPropertyName);
            //}
        }

        /// <summary>
        /// The <see cref="AllProducts" /> property's name.
        /// </summary>
        public const string AllSubstancesPropertyName = "AllSubstances";

        private ObservableCollection<SubstanceViewModel> allSubstances;

        /// <summary>
        /// Gets the AllProducts property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<SubstanceViewModel> AllSubstances
        {
            get { return allSubstances; }

            set
            {
                if (allSubstances == value)
                {
                    return;
                }

                allSubstances = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(AllSubstancesPropertyName);
            }
        }

        public RelayCommand FindProductsCommand { get; private set; }

        private void FindProducts()
        {
            string text;
            if (this.CurrentNewSubstanceForSearch != null)
            {
                text = this.CurrentNewSubstanceForSearch.Name;
            }
            else
            {
                text = this.SearchText;
            }

            this.productModel.GetAllProductsContaingNameAync(text, (products, error) =>
            {
                if (error != null)
                {
                    // Display error, normally this would be done through a property
                    MessageBox.Show(error.Message);
                    return;
                }

                this.SearchResults = new ObservableCollection<UserProductViewModel>(products);
            });
        }

        public SubstanceViewModel CurrentNewSubstanceForSearch { get; set; }

        /// <summary>
        /// The <see cref="SearchResults" /> property's name.
        /// </summary>
        public const string SearchResultsPropertyName = "SearchResults";

        private ObservableCollection<UserProductViewModel> searchResults;

        /// <summary>
        /// Gets the SearchResults property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<UserProductViewModel> SearchResults
        {
            get
            {
                return searchResults;
            }

            set
            {
                if (searchResults == value)
                {
                    return;
                }

                searchResults = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(SearchResultsPropertyName);
            }
        }

        public string SearchText { get; set; }
    }
}